home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Turnbull China Bikeride
/
Turnbull China Bikeride - Disc 2.iso
/
STUTTGART
/
UTIL
/
FILEUTIL
/
HIERARCH
/
!Hierarchy
/
doc
/
General
< prev
next >
Wrap
Text File
|
1994-11-19
|
14KB
|
320 lines
----------------------------------------------------------------------
Vorwort
----------------------------------------------------------------------
Die üblichen Aktionen zum Übertragen von Daten zwischen Programmen
und Dateisystemen sind jedem, der schon einmal mit einem Archimedes
unter RiscOS gearbeitet hat, bekannt. Für den Benutzer der Fenster-
oberfläche WIMP stellt sich daß sehr einfach und intuitiv dar.
Programmierer aus der Amiga-, Macintosh- oder Windows-Szene könnten
jetzt vermuten, daß hinter diesem einfachen Verfahren des Icon-Herum
schiebens eine ganze Menge Programmierarbeit steckt. Leute, die zum
erstenmal vor einem Archimedes sitzen, kann man jedenfalls immer
daran erkennen, daß sie eine Datei speichern wollen, indem sie die
mittlere Maustaste drücken (und meist gedrückt halten), mit dem Maus-
zeiger auf 'Save' gehen, diesen Menüpunkt dann irgendwie anwählen und
sich wundern, daß kein typischer File-Requester erscheint.
Es ist bei weitem nicht so kompliziert! Ganz im Gegenteil. Die
einzige Voraussetzung, die man erfüllen muß, um nachfolgende Er-
läuterungen zu verstehen, sind Kenntnisse über das Message-System
des WIMP. Man kommt ohnehin nicht drumherum, wenn man eine Multi-
tasking-Applikation unter RiscOS entwickeln will.
----------------------------------------------------------------------
Das Data Transfer Protocol
----------------------------------------------------------------------
Aus Programmierersicht läßt sich der Vorgang der Übertragung
von Daten zwischen Applikationen noch einfacher verstehen. Ein
wesentlicher Unterschied von RiscOS zu anderen Betriebssystem ist
schon einmal die Tatsache, daß alle Dateisysteme unter RiscOS auch
nichts anderes als (Module)-Tasks sind. Den krassesten Gegensatz zu
diesem Konzept bildet wohl ein IBM-kompatibler PC, auf dem MS-DOS
läuft.
Für einen Archimedes-Programmierer bedeutet es jedenfalls, daß
er Sonderfälle ausschließen kann: es macht keinen Unterschied,
Daten auf Festplatte zu schreiben oder z.B. einem DTP-System
zu übergeben. Zu diesem Zweck wurde ein Message-Protokoll ent-
worfen, an das sich auch die Dateisysteme halten. Dadurch verrin-
gert sich der Code-Overhead eines Programms zur Datenübertragung
erheblich. Dieses Protokoll kommt mit 7 standardisierten Message-
Strukturen aus:
Message_DataSave 1
Message_DataSaveAck 2
Message_DataLoad 3
Message_DataLoadAck 4
Message_DataOpen 5
Message_RamFetch 6
Message_RamTransmit 7
Die Struktur dieser Messages wird in den beiliegenden Dateien
genauer beschrieben. Diese Datei beschreibt bloß die generellen
Vorgänge und kann als Kurs für Einsteiger angesehen werden.
Wird vom Benutzer eines Programms jetzt eine 'Speicheraktion'
ausgelöst, werden einige (oder alle) Message-Strukturen in einer
festgelegten Reihenfolge zwischen den beteiligten Tasks ver-
sandt. Leider wird der von Acorn definierte Standard nicht in
jedem Fall eingehalten.
1. Das Sichern von Daten in eine Datei.
---------------------------------------
Ausgelöst wird diese Aktion durch den üblichen 'Save as:'-
Dialog eines Programms. Dieser Dialog enthält mindestens
ein Texticon, in das man den Endnamen der zu erzeugenden
Datei schreiben kann sowie ein Icon, das auch den jeweiligen
Typ der Datei anzeigen sollte.
Folgendes geschieht:
- Der Benutzer hat das Icon in ein Verzeichnisfenster
gezogen und 'läßt es los'. Das Programm empfängt
beim nächsten Aufruf von Wimp_Poll als Rückgabewert
User_Drag_Box.
- Das Programm ruft Wimp_GetPointerInfo auf. Es erhält
folgende Informationen: absolute Koordinaten des
Mauszeigers, Zustand der Maustasten sowie die Handle
des Icons bzw. Fensters, in denen der Mauszeiger sich
gerade befindet.
- Das Programm schickt Message_DataSave an den Filer,
indem es die vorher ermittelten Informationen benutzt.
Weiterhin übergeben wird der Dateiendname, den der
Benutzer der Datei gegeben hat.
- Der Filer antwortet mit Message_DataSaveAck. Diese
Message enthält den kompletten Pfadnamen der zu er-
zeugenden Datei.
- Das Programm sichert die Daten in diese Datei.
- Das Programm schickt Message_DataLoad an den Filer.
Diese Message enthält den zuvor übermittelten
kompletten Pfadnamen der erzeugten Datei.
- Der Filer antwortet mit Message_DataLoadAck.
Wer die letzten beiden Schritte für überflüssig hält,
sollte sich das folgende Beispiel durchlesen.
2. Das Übertragen von Daten zu einer anderen Applikation.
---------------------------------------------------------
Der 'Save as:'-Dialog findet wieder Anwendung, mit dem
Unterschied, daß das Icon nicht in einem Verzeichnis-
fenster, sondern auf dem Iconbar-Icon oder Fenster einer
anderen Applikation 'abgelegt' wird.
- Wimp_Poll des übertragenden Programms ergibt ein
Ereignis des Typs User_Drag_Box (siehe oben).
- Das übertragende Programm ruf Wimp_GetPointerInfo auf.
- Das Programm schickt Message_DataSave an das empfangende
Programm, indem es die vorher ermittelten Informationen
benutzt.
=> Bisher unterscheidet sich also noch nichts vom ersten
Beispiel. Es ist für die übertragende Applikation
auch nicht ohne weiteres erkennbar, um was für eine
Art von Task es sich hier handelt.
- Das empfangende Programm anwortet wie erwartet mit
Message_DataSaveAck. Diese Message enthält üblicherweise
den Pfadnamen einer temporären Datei <Wimp$Scrap>.
- Das übertragende Programm sichert die Daten in diese
temporäre Datei. (Der Filer erweitert die System-
variable <Wimp$Scrap> zu einem kompletten Pfadnamen.)
- Das übertragende Programm schickt Message_DataLoad an
das empfangende Programm. Diese Message enthält den
Pfadnamen aus der empfangenen Message_DataSaveAck,
also z.B. <Wimp$Scrap>.
- Das empfangende Programm lädt die Daten aus der tempo-
rären Datei und löscht diese Datei.
- Das empfangende Programm antwortet wie erwartet mit
Message_DataLoadAck.
=> Wie man sieht, braucht ein Programm also gar nicht
zu 'wissen', mit wem es zu tun hat. Der Vorgang der
Datenübertragung ist immer der gleiche. Es folgt
eine Kurzfassung der Vorgänge. Nehmen wir an, A will
B die Datei C übertragen. D sei der Pfadname der
temporären oder endgültigen Datei. Der Unterschied
zwischen C und D ist, daß D nicht nur den gewünschten
Endnamen der Datei, sondern auch Pfadangaben beinhal-
tet. Der unter RiscOS 2 übliche Pfadname für D ist
<Wimp$Scrap> = z.B. 'SCSI::HD0.$.!System.ScrapFile'.
1. A -> B: Message_DataSave C
2. B -> A: Message_DataSaveAck D
3. A: Sichert Daten in D
4. A -> B: Message_DataLoad D
5: B: Lädt die Daten aus D und löscht D
6: B -> A: Message_DataLoadAck D
Der entscheidende Unterschied, der A verborgen bleibt,
ist das Verhalten von B nach Schritt 4. Der Filer wird
Schritt 5 natürlich nicht ausführen, er antwortet aber
korrekt. Bekommt A auf Message_DataLoad keine Antwort
der Form DataLoadAck, so hat A die Datei D zu löschen
und eine Fehlermeldung auszugeben: 'Data transfer
failed: Receiver died.'
3. Laden von Daten aus einer Datei
----------------------------------
Wie sich aus den obigen Beispiel ersehen läßt, hat eine
Applikation (!) eine Datei zu laden, wenn Message_DataLoad
empfangen wird.
Der übliche Weg, einem Programm eine derartige Nachricht
zukommen zu lassen, ist ein Icon aus einem Verzeichnisfenster
auf ein Fenster oder das Iconbar-Icon des Programms zu ziehen.
Folgendes passiert:
1. Message_DataLoad <Kompl.PfadName> wird empfangen.
2. <Kompl.PfadName> laden.
3. Message_DataLoadAck <Kompl.PfadName> senden.
=> Zu beachten ist, daß in Schritt 2 die Datei nach dem
Einlesen nicht gelöscht werden darf. Es muß also
festgehalten werden, ob vorher Message_DataSave
empfangen wurde, was ein sicheres Anzeichen dafür ist,
daß es sich bei der 'Gegenstelle' ebenfalls um eine
Applikation handelt.
4. Laden von Daten einer anderen Applikation
--------------------------------------------
Hier handelt es sich um Fall 2, nur von der Seite des
Empfängers aus gesehen. Ich fasse nochmal zusammen:
1. Message_DataSave <DateiEndName> wird empfangen.
2. Message_DataSaveAck <Wimp$Scrap> senden.
3. Das andere Programm speichert in <Wimp$Scrap>.
4. Message_DataLoad <Wimp$Scrap> wird empfangen.
5. <Wimp$Scrap> laden und löschen.
6. Message_DataLoadAck <Wimp$Scrap> senden.
=> In diesem Fall muß die temporäre Datei gelöscht
werden. Siehe Fall 3.
=> Schritt 5 darf erst ausgeführt werden, wenn auch
die Aufforderung mittels Message_DataLoad einge-
gangen ist (Schritt 4).
5. Automatisches Laden von Daten aus Dateien.
---------------------------------------------
Dieser Fall unterscheidet sich nicht großartig von Fall 3,
ist aber eines der Grundelemente des Desktops. Wie auch
unter anderen Betriebssystemen kann man Dateien 'öffnen',
'starten' bzw. anzeigen lassen, indem man einen Doppel-
klick über dem Icon der gewünschten Datei ausführt.
Folgendes passiert:
1. Message_DataOpen <DateiEndName> wird empfangen.
2. <DateiEndName> laden.
3. Message_DataLoadAck <DateiEndName> senden.
=> Die Bedingung, ob eine Datei zu laden ist, ist deren
Dateityp, der in der Message übermittelt wird. !Edit
reagiert normalerweise auch nur auf Doppelklicks,
wenn sie über Text-Dateien stattfinden.
=> Antwortet keine Applikation auf Message_DataOpen, so
führt der Filer *Run <DateiEndName> aus, greift also
auf eventuell definierte Systemvariablen zurück. Ist
für den entsprechenden Dateityp nichts definiert,
wird die Fehlermeldung 'No run action specified for
this filetype' erzeugt.
=> Soll eine Datei aufgrund Message_DataOpen geladen
werden, so ist das vor dem nächsten Aufruf von
Wimp_Poll auch mit Message_DataLoadAck <DateiEndName>
zu bestätigen. Geschieht das nicht, dann hat der
Benutzer dummerweise zwei Exemplare des gleichen
Programms auf dem Desktop, die beide die gleiche
Datei geladen haben. Tritt dann noch der Fall auf,
daß die bereits geladene Applikation nicht genug
Speicher hat, um die Datei zu laden, wird die neu
gestarte Applikation ebenfalls nicht genug Speicher
zu Verfügung haben ... sprich: doppelte Fehlermeldung.
6. Datenübertragung via RAM
---------------------------
Es gibt eine Erweiterung des Data Transfer Protocol, um
die Übertragung von Daten zwischen zwei Applikationen zu
beschleunigen. Hierbei werden die zu transferrierenden
Daten nicht in einer temporären Datei zwischengelagert,
sondern via Wimp_Transferblock direkt zwischen den
Addressräumen der zwei beteiligten Programmen übertragen.
Das oben beschriebene Protokoll wird wie folgt erweitert:
Übertragen von Daten zu einer anderen Applikation
-------------------------------------------------
1. A -> B: Message_DataSave <DateiEndName>
2. B -> A: Message_RAMFetch
3. A -> B: Message_RAMTransmit <data>
4. B -> A: Message_RAMFetch ...
Die letzten beiden Schritte werden wiederholt, bis
alle Daten gesendet und empfangen wurden.
Laden von Daten einer anderen Applikation
-----------------------------------------
1. B -> A: Message_DataSave <DateiEndName>
2. A -> B: Message_RAMFetch
3. A: Wenn Schritt 2 von B nicht bestätigt wird,
wird vorgegangen wie üblich:
Message_DataSaveAck <Wimp$Scrap> usw ...
ansonsten: B -> A: Message_RAMTransmit
4. A: Daten empfangen und verarbeiten.
5. Solange der mittels Message_RAMTransmit proto-
kollierte Buffer voll ist:
A -> B: Message_RAMFetch
B: Wimp_TransferBlock
B -> A: Message_RAMTransmit
=> Wenn die erste Message_RAMFetch von der übertragenden
Applikation B nicht bestätigt wird (also in Form einer
User_Message_Acknowledge, Typ 19 zurück zum Absender
A gelangt), sollte die empfangende Applikation A das
übliche Verfahren via temporärer Datei verwenden.
=> Wenn eine der nachfolgenden Message_RAMFetch nicht
von B (mit Message_RAMTransmit) beantwortet werden,
sollte A den Empfang kommentarlos (d.h., ohne Fehler-
meldung) abbrechen.
=> Die Daten selbst werden von B mit Wimp_TransferBlock
übertragen. Die dazu benötigten Informationen, also
die Adresse und die Größe des Buffers werden von A
mittels Message_RAMFetch mitgeteilt.
=> Abbruchbedingung für den Übertragungsprozeß ist ein
nicht voller Buffer. Ist die Anzahl der insgesamt zu
übertragenden Bytes genau ein Mehrfaches der Größe
des Buffers, so ist ein abschließendes Paar von
Nachrichten zwischen den Applikationen zu senden,
bei denen 0 Bytes zu übertragen sind.
=> Aus den Beschreibungen im Programmers Reference Manual
geht leider nicht hervor, ob es erlaubt ist, die
Größe des Buffers während der Übertragung zu ver-
ändern. Hier gilt wieder: einige Programme reagieren
in dieser Hinsicht empfindlich. Man sollte also darauf
verzichten.